//
//  NSObject+ZBpublic extension.swift
//  AJiTai
//
//  Created by BO ZHOU on 2020/5/16.
//  Copyright © 2020 BO ZHOU. All rights reserved.
//

import Foundation

public extension NSObject {
    @objc    
    // 获取并打印类的所有方法
    func printMethods() {
        var m_count:UInt32 = 0;

        if let methods = class_copyMethodList(type(of: self), &m_count){
            debugPrint(methods[0]);

            for i in 0..<m_count{
                let m = methods[Int(i)];
                let sel = method_getName(m);
                let name = sel_getName(sel);
                debugPrint("方法:\(name): \(NSStringFromSelector(sel))");
            }
        }
    }
    
    // 获取并打印类的所有成员变量
    func printProperties() {
        var p_count : UInt32 = 0;

        if let propertys = class_copyPropertyList(type(of: self), &p_count) {
            
            for i in 0..<p_count{
                let p = propertys[Int(i)];
                let name = ivar_getName(p);
                debugPrint("成员变量:\(String(describing: name)): \(String(cString:property_getName(p)))");
            }
        }
    }

    /// 获取纯类名

    /**
     print(self.getClassName())
     print(type(of: self).getClassName())
     print(self.getFullClassName())
     print(type(of: self).getFullClassName())
     */
    func getClassName() -> String {
        return String(describing: self.classForCoder)
    }

    class func getClassName() -> String {
        return String(describing: self)
    }

    /// 获取target名.类名
    func getFullClassName() -> String {
        return NSStringFromClass(self.classForCoder)
    }

    class func getFullClassName() -> String {
        return NSStringFromClass(self.classForCoder())
    }
    
    
    /**
     运行时交换两个方法的实现
     
     - paramter: originalSelector 被交换的方法 (该方法只能是系统方法, 自定义方法不能被交换)
     - paramter: swizzledSelector 新方法
     */
    class func exchange(originalSelector: Selector, swizzledSelector: Selector) {
        let originalMethod = class_getInstanceMethod(self.classForCoder(), originalSelector)
        let swizzledMethod = class_getInstanceMethod(self.classForCoder(), swizzledSelector)
        guard (originalMethod != nil && swizzledMethod != nil) else {
            return
        }
        if class_addMethod(self.classForCoder(), originalSelector, method_getImplementation(swizzledMethod!), method_getTypeEncoding(swizzledMethod!)) {
            class_replaceMethod(self.classForCoder(), swizzledSelector, method_getImplementation(originalMethod!), method_getTypeEncoding(originalMethod!))
        } else {
            method_exchangeImplementations(originalMethod!, swizzledMethod!)
        }
    }

    /**
     * 子类实现这个方法, 用于在app启动时候执行运行时的一些指令
     * 如果方法希望被子类重写, 必须加上@objc
     */
    @objc open class func initRunTime() {

    }
}
